package com.mybatis.config;

import com.mybatis.annotation.Delete;
import com.mybatis.annotation.Insert;
import com.mybatis.annotation.Select;
import com.mybatis.annotation.Update;
import com.util.log.Logger;

import java.io.IOException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 读取与解析配置信息
 * 读取xml后将属性和连接数据库的操作封装在MyConfiguration对象中供后面的组件调用
 */
public class MyConfiguration {
    private static final Logger log = Logger.getLogger(MyConfiguration.class);

    /**
     * 读取配置文件里的jdbc配置信息
     */
    private static final Properties jdbcProperties = new Properties();

    static {
        Properties properties = new Properties();
        try {
            properties.load(MyConfiguration.class.getClassLoader().getResourceAsStream("application.yml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (properties.getProperty("jdbc.driverClassName") == null
                || properties.getProperty("jdbc.url") == null
                || properties.getProperty("jdbc.username") == null
                || properties.getProperty("jdbc.password") == null) {
            throw new RuntimeException("缺少jdbc配置");
        }
        jdbcProperties.setProperty("jdbc.driverClassName", properties.getProperty("jdbc.driverClassName"));
        jdbcProperties.setProperty("jdbc.url", properties.getProperty("jdbc.url"));
        jdbcProperties.setProperty("jdbc.username", properties.getProperty("jdbc.username"));
        jdbcProperties.setProperty("jdbc.password", properties.getProperty("jdbc.password"));

        try {
            Class.forName(properties.getProperty("jdbc.driverClassName")); // 加载类
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        log.trace("读取配置文件application.yml里的jdbc配置: " + jdbcProperties);
    }

    /**
     * 建立数据库连接
     *
     * @return
     */
    public Connection getConnection() throws SQLException {
        return DriverManager.getConnection(jdbcProperties.getProperty("jdbc.url"),
                jdbcProperties.getProperty("jdbc.username"), jdbcProperties.getProperty("jdbc.password"));
    }

    /**
     * 生成mapper的functionInfoMap
     *
     * @param clazz mapper接口的Class对象
     * @return Map<String, FunctionInfo>
     */
    public Map<String, MapperFunctionInfo> generateFunctionInfoMapOfMapper(Class<?> clazz) {
        Map<String, MapperFunctionInfo> functionInfoMap = new HashMap<>();
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            MapperFunctionInfo functionInfo = new MapperFunctionInfo();
            functionInfo.setName(method.getName());

            // 解析sql语句注解
            Select select = method.getAnnotation(Select.class);
            if (select != null) {
                functionInfo.setSqlType("SELECT");
                functionInfo.setSql(select.value());
                functionInfo.setResultType(select.resultType());
            } else {
                Insert insert = method.getAnnotation(Insert.class);
                if (insert != null) {
                    functionInfo.setSqlType("INSERT");
                    functionInfo.setSql(insert.value());
                    functionInfo.setResultType(int.class);
                } else {
                    Delete delete = method.getAnnotation(Delete.class);
                    if (delete != null) {
                        functionInfo.setSqlType("DELETE");
                        functionInfo.setSql(delete.value());
                        functionInfo.setResultType(int.class);
                    } else {
                        Update update = method.getAnnotation(Update.class);
                        if (update != null) {
                            functionInfo.setSqlType("UPDATE");
                            functionInfo.setSql(update.value());
                            functionInfo.setResultType(int.class);
                        } else {
                            throw new RuntimeException("方法上未定义任何sql注解");
                        }
                    }
                }
            }
            functionInfoMap.put(functionInfo.getName(), functionInfo);
        }
        log.trace("生成mapper的functionInfoMap " + functionInfoMap);
        return functionInfoMap;
    }
}
